---
title: 接口 vs 抽象类
description: 辨析接口和抽象类的区别与适用场景
sidebar_position: 4
---

# 接口 vs 抽象类

## 基本概念与区别

### 抽象类的特性

1. **定义特点**
   - 不允许被实例化，只能被继承
   - 可以包含属性和方法
   - 方法可以有具体实现，也可以是抽象方法
   - 子类必须实现所有抽象方法

2. **代码示例**

```typescript
abstract class Logger {
  private name: string;
  private enabled: boolean;
  private minPermittedLevel: Level;

  constructor(name: string, enabled: boolean, minPermittedLevel: Level) {
    this.name = name;
    this.enabled = enabled;
    this.minPermittedLevel = minPermittedLevel;
  }

  public log(level: Level, message: string): void {
    const loggable = this.enabled && (this.minPermittedLevel <= level);
    if (!loggable) return;
    this.doLog(level, message);
  }

  protected abstract doLog(level: Level, message: string): void;
}
```

### 接口的特性

1. **定义特点**
   - 不能包含属性（除了静态常量）
   - 只能声明方法，方法不能包含实现代码
   - 类必须实现接口中声明的所有方法

2. **代码示例**

```typescript
interface Filter {
  doFilter(req: RpcRequest): void;
}

class AuthenticationFilter implements Filter {
  doFilter(req: RpcRequest): void {
    // 鉴权逻辑实现
  }
}
```

## 本质区别

1. **关系类型**
   - 抽象类：表示 is-a 关系，是一种继承关系
   - 接口：表示 has-a 关系，是一种能力的声明

2. **设计目的**
   - 抽象类：主要用于代码复用
   - 接口：主要用于解耦，是一种行为的抽象

3. **设计思路**
   - 抽象类：自下而上的设计思路，从具体到抽象
   - 接口：自上而下的设计思路，先定义接口再考虑实现

## 如何选择使用

1. **使用抽象类的场景**
   - 需要表示 is-a 关系
   - 需要在多个子类之间共享代码
   - 需要继承默认实现的方法
   - 需要声明非 public 的成员

2. **使用接口的场景**
   - 需要表示 has-a 关系
   - 需要实现多个接口（多继承）
   - 需要定义一组行为规范
   - 需要提高代码的可扩展性

## 最佳实践建议

1. **选择标准**
   - 如果主要目的是代码复用，使用抽象类
   - 如果主要目的是定义规范，使用接口
   - 如果不确定，优先使用接口

2. **设计建议**
   - 接口设计要保持简单，单一职责
   - 抽象类层次不要过深
   - 优先使用组合而非继承
   - 面向接口编程而非实现

## 总结

接口和抽象类是面向对象编程中两个重要的概念，各自有其适用场景：

- 抽象类通过继承关系实现代码复用，适合表示具有层次结构的对象关系
- 接口通过定义行为契约实现解耦，适合定义对象的能力

在实际开发中，应该根据具体场景选择合适的方式，可以同时使用两者来实现更灵活的设计。记住一点：抽象类是对"类"的抽象，而接口是对"行为"的抽象。
